#include "SI_NS.h"
#include "LED.h"
#include "SI.h"
#include "SOSZ.h"
#include "Relay.h"
#include "Button.h"
#include "GA.h"

/*enum SI_STATE_NS {  DO NOT CHANGE ORDER OF STATES!!!
	SI_STATE_IDLE,
	SI_STATE_NS_smokeCheck_waitForAck,
	SI_STATE_NS_smokeCheck_Acked,
	SI_STATE_NS_alarmWaitForAck,
	SI_STATE_NS_alarmWaitForReset,
	SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear,
	SI_STATE_NS_resetOn,
	SI_STATE_NS_resetOff,
	SI_STATE_NS_clearTimer,
	SI_STATE_NS_confirmTimer
};*/
extern struct SI_threadInfo_t SI_threadInfo[SI_ACTIVE];

void SI_NS_alarmIDLE(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_smokeCheck_waitForAck(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_alarmWaitForAck(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_smokeCheck_Acked(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_alarmWaitForReset(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
//void SI_NOSHalarmResetON(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
//void SI_NOSHalarmResetOFF(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_resetOff(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_resetOn(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_alarm_enterAlarm(unsigned char i);
void SI_NS_endSmokeCheck(unsigned char i);
void SI_NS_alarmWaitForAck_afterResetAndAlmClear(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_clearTimer(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
void SI_NS_confirmTimer(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed);
RTN_TYPE SI_stateDuringCheckIfAcked(unsigned char i);

const struct siStateInfo_t siStateInfo [] = {
		// DO NOT CHANGE THE ORDER OF THE TABLE ENTRIES!!!									    	locAlm      locSuper  	gloAlm    	gloSuper	 relay
		{SI_STATE_IDLE, 					SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	Relay_Off},
		{SI_STATE_alarmEntryTimer, 			SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_FAST, 	RATE_SLOW, 	RATE_FAST, 	RATE_SLOW, 	Relay_Off},
		{SI_STATE_alarmEntryTimerFWS_waitForAck, SOSZ_clearSOSZ_SILoAlm, SI_NS_alarmIDLE, 			RATE_FAST, 	RATE_SLOW, 	RATE_FAST, 	RATE_SLOW, 	Relay_Off},
		{SI_STATE_alarmEntryTimerFWS_Acked, SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_ON, 	RATE_ON, 	RATE_ON, 	RATE_ON, 	Relay_Off},
		{SI_STATE_alarmWaitForAck, 			SOSZ_notifySOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_FAST, 	RATE_SLOW, 	RATE_FAST, 	RATE_SLOW, 	Relay_On},
		{SI_STATE_alarmWaitForResetOrFltClear, SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_ON, 	RATE_ON, 	RATE_ON, 	RATE_ON, 	Relay_On},
		{SI_STATE_alarmWaitForAck_afterResetOrFltClear, SOSZ_clearSOSZ_SILoAlm, SI_NS_alarmIDLE, 	RATE_SLOW, 	RATE_SLOW_SLOW, 	RATE_SLOW, 	RATE_SLOW_SLOW, 	Relay_Off},

		{SI_STATE_faultWaitForAck, 			SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	Relay_Off},
		{SI_STATE_faultWaitForFltClear, 	SOSZ_clearSOSZ_SILoAlm, 	SI_NS_alarmIDLE, 			RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	Relay_Off},
		{SI_STATE_faultWaitForAck_afterFltClear, SOSZ_clearSOSZ_SILoAlm, SI_NS_alarmIDLE, 			RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	RATE_OFF, 	Relay_Off},

		// DO NOT CHANGE THE ORDER OF THE TABLE ENTRIES!!!
		{SI_STATE_NS_smokeCheck_waitForAck, SOSZ_clearSOSZ_SILoAlm,    SI_NS_smokeCheck_waitForAck, RATE_FAST, 	RATE_SLOW, 	RATE_FAST, 	RATE_SLOW, 	Relay_Off},
		{SI_STATE_NS_smokeCheck_Acked, 		SOSZ_clearSOSZ_SILoAlm, 	SI_NS_smokeCheck_Acked, 	RATE_ON,   	RATE_ON, 	RATE_ON, 	RATE_ON, 	Relay_Off},
		{SI_STATE_NS_alarmWaitForAck, 		SOSZ_notifySOSZ_SILoAlm, 	SI_NS_alarmWaitForAck, 		RATE_FAST, 	RATE_SLOW, 	RATE_FAST, 	RATE_SLOW, 	Relay_On},
		{SI_STATE_NS_alarmWaitForReset, 	SOSZ_notifySOSZ_SILoAlm, 	SI_NS_alarmWaitForReset, 	RATE_ON,   	RATE_ON, 	RATE_ON, 	RATE_ON, 	Relay_On},
		{SI_STATE_NS_resetOn, 				SOSZ_notifySOSZ_SILoAlm, 	SI_NS_resetOn, 				RATE_ON,   	RATE_ON, 	RATE_ON,  	RATE_ON, 	Relay_On},
		{SI_STATE_NS_resetOff, 				SOSZ_notifySOSZ_SILoAlm, 	SI_NS_resetOff, 			RATE_ON,   	RATE_ON, 	RATE_ON,  	RATE_ON, 	Relay_On},
		{SI_STATE_NS_clearTimer, 			SOSZ_notifySOSZ_SILoAlm, 	SI_NS_clearTimer, 			RATE_ON,   	RATE_ON, 	RATE_ON,  	RATE_ON, 	Relay_On},
		{SI_STATE_NS_confirmTimer, 			SOSZ_clearSOSZ_SILoAlm, 	SI_NS_confirmTimer, 		RATE_ON,   	RATE_ON, 	RATE_OFF, 	RATE_OFF, 	Relay_Off},
		{SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear,
											SOSZ_clearSOSZ_SILoAlm, SI_NS_alarmWaitForAck_afterResetAndAlmClear,
																								 RATE_SLOW, RATE_SLOW_SLOW, RATE_OFF, 	RATE_OFF, 	Relay_Off}
};
pSiStateInfo_t SI_test_NS_returnCurrentState(unsigned char si)
{
	enum SI_STATE state = SI_threadInfo[si].alarmState;
	pSiStateInfo_t pSiStateInfo = (pSiStateInfo_t)&siStateInfo[state];
	return pSiStateInfo;
}
void memfillC(unsigned char * dest, unsigned char * src, unsigned int bytes)
{
	while (bytes--)
	{
		*dest = *src;
		dest++; src++;
	}
}
void SI_test_NS_packDesiredState(pSiStateInfo_t pDest, enum SI_STATE me)
{
	pSiStateInfo_t pSource = (pSiStateInfo_t)&siStateInfo[me];
	memfillC((unsigned char *)pDest, (unsigned char *)pSource, sizeof(struct siStateInfo_t));
}
RTN_TYPE SI_stateDuring(unsigned char i)
{
	enum SI_STATE state = SI_threadInfo[i].alarmState;
	RTN_TYPE rtn = RTN_ERROR_GEN;
	if (state == SI_STATE_IDLE || state <= SI_STATE_NS_last || state >= SI_STATE_NS_begin)
	{
		siStateInfo[state].pSiAlmNotify(1<<i);
		siStateInfo[state].pStateFxnDuring(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
		rtn = RTN_SUCCESS;
	}
//	SI_stateDuringCheckIfAcked(i);
	return rtn;
}
RTN_TYPE SI_stateValidateState(unsigned char i)
{
	enum SI_STATE state = SI_threadInfo[i].alarmState;
	RTN_TYPE rtn = RTN_ERROR_GEN;

	if (state == SI_STATE_IDLE || state <= SI_STATE_NS_last || state >= SI_STATE_NS_begin)
	{
		rtn = RTN_SUCCESS;
	}
	return rtn;
}
RTN_TYPE SI_stateDuringDriveResources(unsigned char i)
{
	enum LED_INDEX globalAlarmLed = SI_threadInfo[i].globalAlarmLed;
	enum LED_INDEX alarmLed = SI_threadInfo[i].alarmLed;
	enum SI_STATE state = SI_threadInfo[i].alarmState;
//	unsigned char isAcked = SI_threadInfo[i].isAcked;
	RTN_TYPE rtn = RTN_ERROR_GEN;

	if (SI_stateValidateState(i))
	{
		enum Relay_Setting relaySetting =  siStateInfo[state].myRelaySetting;
		SI_relayHelper(alarmLed, globalAlarmLed, relaySetting);
//		if (globalAlarmLed == LED_ALARMS)
//		{
//			REL_resourceArray_requestRelay(Relay_Alarm, alarmLed, relaySetting);
//		}
//		else if (globalAlarmLed == LED_SUPER)
//		{
//			REL_resourceArray_requestRelay(Relay_Fault, alarmLed, relaySetting);
//		}
		enum RATES myRate = RATE_OFF;
		if (globalAlarmLed == LED_ALARMS)
		{
//			myRate = siStateInfo[state].alarmLedsRate;
			LED_setRate(alarmLed, siStateInfo[state].alarmLedsRate);
			//LED_setRate(globalAlarmLed, myRate);
			enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
			LED_resourceArray_requestRate(glob, alarmLed, myRate);
		}
		else if (globalAlarmLed == LED_SUPER)
		{
			myRate = siStateInfo[state].supervisoryRate;
			LED_setRate(alarmLed, myRate);
			//LED_setRate(globalAlarmLed, myRate);
			enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
			LED_resourceArray_requestRate(glob, alarmLed, myRate);
		}
		rtn = RTN_SUCCESS;
	}
	return rtn;
}
RTN_TYPE SI_stateDuringCheckIfAcked(unsigned char i)
{
	enum SI_STATE state = SI_threadInfo[i].alarmState;
	unsigned char isAcked = SI_threadInfo[i].isAcked;

	enum LED_INDEX globalAlarmLed = SI_threadInfo[i].globalAlarmLed;
	enum LED_INDEX alarmLed = SI_threadInfo[i].alarmLed;

	RTN_TYPE rtn = RTN_ERROR_GEN;

	if (SI_stateValidateState(i))
	{
		siStateInfo[state].pSiAlmNotify(1<<i);
		if (isAcked)
		{
			siStateInfo[state].pStateFxnDuring(alarmLed, globalAlarmLed);
		}
		else
		{
			SI_NS_alarmWaitForAck(alarmLed, globalAlarmLed);
		}
		SI_stateDuringDriveResources(i);
		rtn = RTN_SUCCESS;
	}
	return rtn;
}

void SI_stateChangeState(enum SI_STATE newState, unsigned char i)
{
	SI_threadInfo[i].alarmState = newState;
	SI_stateDuring(i);
}
void SI_NS_alarmIDLE(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	LED_setRate(almLed, RATE_OFF);
	//LED_setRate(globalAlarmLed, RATE_OFF);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_OFF);
	SI_relayHelper(almLed, globalAlarmLed, Relay_Off);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
}
void SI_NS_waitForAckLeds(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	if (globalAlarmLed == LED_ALARMS)
	{
		LED_setRate(almLed, RATE_FAST);
		//LED_setRate(globalAlarmLed, RATE_FAST);
		enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
		LED_resourceArray_requestRate(glob, almLed, RATE_FAST);
	}
	else if (globalAlarmLed == LED_SUPER)
	{
		LED_setRate(almLed, RATE_SLOW);
		//LED_setRate(globalAlarmLed, RATE_SLOW);
		enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
		LED_resourceArray_requestRate(glob, almLed, RATE_SLOW);
	}
	else
	{
		LED_setRate(almLed, RATE_SLOW);
	}
}
void SI_NS_smokeCheck_waitForAck(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SI_NS_waitForAckLeds(almLed, globalAlarmLed);
	SI_relayHelper(almLed, globalAlarmLed, Relay_Off);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	SOSZ_clearSOSZ_SILoAlm(1<<i);
}
void SI_NS_smokeCheck_Acked(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	__no_operation();
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	LED_setRate(almLed, RATE_ON);
	//LED_setRate(globalAlarmLed, RATE_ON);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_ON);
	SI_relayHelper(almLed, globalAlarmLed, Relay_Off);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	SOSZ_clearSOSZ_SILoAlm(1<<i);
}
void SI_NS_alarmWaitForAck(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SI_NS_smokeCheck_waitForAck(almLed, globalAlarmLed);
	SI_relayHelper(almLed, globalAlarmLed, Relay_On);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	SOSZ_notifySOSZ_SILoAlm(1<<i);
}
void SI_NS_alarmWaitForReset(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	LED_setRate(almLed, RATE_ON);
	//LED_setRate(globalAlarmLed, RATE_ON);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_ON);
	SI_relayHelper(almLed, globalAlarmLed, Relay_On);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	SOSZ_notifySOSZ_SILoAlm(1<<i);
}
void SI_NS_alarmWaitForAck_afterResetAndAlmClear(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	//LED_setRate(globalAlarmLed, RATE_OFF);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_OFF);
	SOSZ_clearSOSZ_SILoAlm(1<<i);
	if (SI_threadInfo[i].isAcked == 1)
	{
		if (globalAlarmLed == LED_ALARMS)
		{
			LED_setRate(almLed, RATE_SLOW);
	//		Relay_set(Relay_Alarm, Relay_Off);
		}
		else// if (globalAlarmLed == LED_SUPER)
		{
			LED_setRate(almLed, RATE_SLOW_SLOW);
	//		Relay_set(Relay_Fault, Relay_Off);
		}

	}
	else
	{
		SI_NS_waitForAckLeds(almLed, globalAlarmLed);
	}
	SI_relayHelper(almLed, globalAlarmLed, Relay_Off);

	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
}
void SI_NS_clearTimer(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SOSZ_notifySOSZ_SILoAlm(1<<i);
	LED_setRate(almLed, RATE_ON);
	//LED_setRate(globalAlarmLed, RATE_ON);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_ON);
	SI_relayHelper(almLed, globalAlarmLed, Relay_On);
	// SI_24+ is off
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	__no_operation();
}
void SI_NS_confirmTimer(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SOSZ_clearSOSZ_SILoAlm(1<<i);
	LED_setRate(almLed, RATE_ON);
	//LED_setRate(globalAlarmLed, RATE_OFF);
	enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
	LED_resourceArray_requestRate(glob, almLed, RATE_OFF);
	SI_relayHelper(almLed, globalAlarmLed, Relay_Off);
	// SI_24+ is off
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	__no_operation();
}
void SI_NS_resetOff(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SOSZ_notifySOSZ_SILoAlm(1<<i);
	if (SI_threadInfo[i].isAcked == 1)
	{
		LED_setRate(almLed, RATE_ON);
		//LED_setRate(globalAlarmLed, RATE_ON);
		enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
		LED_resourceArray_requestRate(glob, almLed, RATE_ON);
	}
	else
	{
		SI_NS_waitForAckLeds(almLed, globalAlarmLed);
	}
	SI_relayHelper(almLed, globalAlarmLed, Relay_On);
	// SI_24+ is off
	SI_24VOutput_clear((enum SI_X_mask)1<<i);
	SI_threadInfo[i].inReset = 1;
}
void SI_NS_resetOn(enum LED_INDEX almLed, enum LED_INDEX globalAlarmLed)
{
	unsigned char i = almLed - (unsigned char)LED_SI_1_Alm;
	SOSZ_notifySOSZ_SILoAlm(1<<i);
	if (SI_threadInfo[i].isAcked == 1)
	{
		LED_setRate(almLed, RATE_ON);
		//LED_setRate(globalAlarmLed, RATE_ON);
		enum LED_GLOBAL_INDEX glob = globalLedToIndex(globalAlarmLed);// - LED_GLOBAL_BEGIN;
		LED_resourceArray_requestRate(glob, almLed, RATE_ON);
	}
	else
	{
		SI_NS_waitForAckLeds(almLed, globalAlarmLed);
	}
	SI_relayHelper(almLed, globalAlarmLed, Relay_On);
	// Turn on SI_24+
	SI_24VOutput_set((enum SI_X_mask)1<<i);
	SI_threadInfo[i].inReset = 1;
}
void SI_NS_alarm_enterAlarm(unsigned char i)
{
	SI_threadInfo[i].isAcked = 0;
	if (SI_threadInfo[i].pSI->SmokeCheckTimer)
	{
		SI_threadInfo[i].oneSecTickCount = 0;
		SI_stateChangeState(SI_STATE_NS_smokeCheck_waitForAck, i);
//		SOSZ_clearSOSZ_SILoAlm(1<<i);
//		SI_threadInfo[i].alarmState = SI_STATE_NS_smokeCheck_waitForAck;
//		SI_NS_smokeCheck_waitForAck(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
		return;
	}
	else if (SI_threadInfo[i].pSI->SWLatch == SI_latch_isLatched)
	{
		SI_stateChangeState(SI_STATE_NS_alarmWaitForAck, i);
//		SOSZ_notifySOSZ_SILoAlm(1<<i);
//		SI_threadInfo[i].alarmState = SI_STATE_NS_alarmWaitForAck;
//		SI_NS_alarmWaitForAck(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
	}
	else
	{
		SI_threadInfo[i].oneSecTickCount = 0;
		SI_stateChangeState(SI_STATE_NS_resetOff, i);
//		SOSZ_notifySOSZ_SILoAlm(1<<i);
//		SI_threadInfo[i].alarmState = SI_STATE_NS_resetOff;
//		SI_NS_resetOff(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
	}
	return;
}
void SI_NS_endSmokeCheck(unsigned char i)
{
	// if smokeCheck done, then go to ResetOff if alm active, else go to waitForAckAfterAlmClear
	if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
	{
		SI_threadInfo[i].oneSecTickCount = 0;
		SI_stateChangeState(SI_STATE_NS_resetOff, i);
	}
	else
	{
		SI_threadInfo[i].oneSecTickCount = 0;
		SI_stateChangeState(SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear, i);
	}
}
void SI_NS_alarmPresentAfterReset_transition(unsigned char i)
{
	if (SI_threadInfo[i].isAcked == 1)
	{
		SI_stateChangeState(SI_STATE_NS_alarmWaitForReset, i);
		return;
	}
	else
	{
		SI_stateChangeState(SI_STATE_NS_alarmWaitForAck, i);
		return;
	}
}
void SI_NS_clearTimer_exit(unsigned char i)
{
	SI_threadInfo[i].oneSecTickCount = 0;
	SI_threadInfo[i].inReset = 0;
	if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
	{
		SI_NS_alarmPresentAfterReset_transition(i);
	}
	else
	{
		if (SI_threadInfo[i].pSI->ConfirmationTimer)
		{
			SI_threadInfo[i].oneSecTickCount = 0;
			SI_stateChangeState(SI_STATE_NS_confirmTimer, i);
			return;
		}
		else
		{
			SI_stateChangeState(SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear, i);
			return;
		}
	}
	return;
}
void SI_NS_resetOn_exit(unsigned char i)
{
	SI_threadInfo[i].oneSecTickCount = 0;
	SI_threadInfo[i].inReset = 0;
	if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
	{
		SI_NS_alarmPresentAfterReset_transition(i);
	}
	else
	{
		if (SI_threadInfo[i].pSI->ClearTimer)
		{
			SI_threadInfo[i].oneSecTickCount = 0;
			SI_stateChangeState(SI_STATE_NS_clearTimer, i);
			return;
		}
		else if (SI_threadInfo[i].pSI->ConfirmationTimer)
		{
			SI_threadInfo[i].oneSecTickCount = 0;
			SI_stateChangeState(SI_STATE_NS_confirmTimer, i);
			return;
		}
		else
		{
			SI_stateChangeState(SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear, i);
			return;
		}
	}
	return;
}
void SI_NS_SM(unsigned char i, struct evtArr_s * evts, unsigned char eventOneSecondTick)
{
	enum SI_STATE alarmState = SI_threadInfo[i].alarmState;
	if ((SI_threadInfo[i].alarmState != SI_STATE_IDLE) && (SI_threadInfo[i].isAcked==0))
	{
//		if (alarmState == SI_STATE_NS_alarmWaitForAck || alarmState == SI_STATE_NS_smokeCheck_waitForAck || alarmState == SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear)
		{
			if (evt_yes == BTN_btnEvent_get(eBtnAck))
			{
				BTN_btnEvent_consume(eBtnAck);
				SI_threadInfo[i].isAcked = 1;
			}
		}
	}
	{
		switch (alarmState)
		{
			case SI_STATE_IDLE:
				SI_stateDuring(i);
//				SOSZ_clearSOSZ_SILoAlm(1<<i);
//				SI_NS_alarmIDLE(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
				if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
				{
					SI_NS_alarm_enterAlarm(i);
					break;
				}
				break;
			case SI_STATE_NS_smokeCheck_waitForAck:
				SI_stateDuring(i);
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->SmokeCheckTimer)
					{
						SI_NS_endSmokeCheck(i);  // if smokeCheck done, then go to ResetOff if alm active, else go to waitForAckAfterAlmClear
						break;
					}
				}
				if (SI_threadInfo[i].isAcked == 1)
				{
					SI_stateChangeState(SI_STATE_NS_smokeCheck_Acked, i);
//					SI_threadInfo[i].alarmState = SI_STATE_NS_smokeCheck_Acked;
//					SI_NS_smokeCheck_Acked(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
					break;
				}
				break;
			case SI_STATE_NS_smokeCheck_Acked:
				SI_stateDuring(i);
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->SmokeCheckTimer)
					{
						SI_NS_endSmokeCheck(i);  // if smokeCheck done, then go to ResetOff if alm active, else go to waitForAckAfterAlmClear
						break;
					}
				}
				break;
			case SI_STATE_NS_alarmWaitForAck:
				// this state is only valid for latched non-shorting input
				SI_stateDuring(i);
//				SI_NS_alarmWaitForAck(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
//				SOSZ_notifySOSZ_SILoAlm(1<<i);
				if (SI_threadInfo[i].isAcked == 1)
				{
//					if (SI_threadInfo[i].pSI->SWLatch == SI_latch_isLatched) {
					SI_stateChangeState(SI_STATE_NS_alarmWaitForReset, i);//SI_threadInfo[i].alarmState = SI_STATE_NS_alarmWaitForReset;
//					SI_NS_alarmWaitForReset(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
//					}
//					else {} // not a valid transition
					break;
				}

				break;
			case SI_STATE_NS_resetOff:
				SI_stateDuring(i);
//				SOSZ_notifySOSZ_SILoAlm(1<<i);
//				SI_NS_resetOn(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->ResetOffTimer)
					{
						SI_threadInfo[i].oneSecTickCount = 0;
						SI_stateChangeState(SI_STATE_NS_resetOn, i);
						break;
					}
					break;
				}
				__no_operation();
				break;
			case SI_STATE_NS_resetOn:
				SI_stateDuring(i);
//				SOSZ_notifySOSZ_SILoAlm(1<<i);
//				SI_NS_resetOff(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->ResetOnTimer)
					{
						SI_NS_resetOn_exit(i);
					}
					break;
				}
				__no_operation();
				break;
			case SI_STATE_NS_clearTimer:
				SI_stateDuring(i);
				if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
				{
					SI_NS_alarmPresentAfterReset_transition(i);
					break;
				}
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->ClearTimer)
					{
						SI_NS_clearTimer_exit(i);
						break;
					}
					break;
				}				__no_operation();
				break;
			case SI_STATE_NS_confirmTimer:
				SI_stateDuring(i);
				if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
				{
					SI_NS_alarmPresentAfterReset_transition(i);
					break;
				}
				if (eventOneSecondTick)
				{
					if (SI_threadInfo[i].oneSecTickCount++ == SI_threadInfo[i].pSI->ConfirmationTimer)
					{
//						SI_threadInfo[i].isAcked = 0;
						SI_stateChangeState(SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear, i);
						break;
					}
					break;
				}
//				SOSZ_clearSOSZ_SILoAlm(1<<i);
//				SI_NS_confirmTimer(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
				__no_operation();
				break;
			case SI_STATE_NS_alarmWaitForReset:
				SI_stateDuring(i);
//				SOSZ_notifySOSZ_SILoAlm(1<<i);
//				SI_NS_alarmWaitForReset(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
				if (evt_yes == BTN_btnEvent_get(eBtnReset))
				{
					//BTN_btnEvent_consume(eBtnReset);  // do not consume, so others may also reset...event will be consumed after all SI's go through SM
//					SI_threadInfo[i].alarmState = SI_STATE_NS_resetOff;
//					SOSZ_notifySOSZ_SILoAlm(1<<i);
//					SI_NS_resetOff(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
					SI_threadInfo[i].oneSecTickCount = 0;
					SI_stateChangeState(SI_STATE_NS_resetOff, i);
					break;
				}
				break;
			case SI_STATE_NS_alarmWaitForAck_afterResetAndAlmClear:
				SI_stateDuring(i);
				if (SI_threadInfo[i].adcState == SI_ADC_ALARM)
				{
					SI_NS_alarm_enterAlarm(i);
					break;
				}
//				if (SI_ackBtnLogic() == SI_threadInfo[i].alarmLed)
//				if (evts->evt[eBtnAck].evtData == SI_threadInfo[i].alarmLed)
				if (SI_threadInfo[i].isAcked == 1)
				{
					if (evt_yes == BTN_btnEvent_get(eBtnAck))
					{
						BTN_btnEvent_consume(eBtnAck);
						SI_stateChangeState(SI_STATE_IDLE, i);
						SI_threadInfo[i].isAcked = 0;
						break;
	//					SI_threadInfo[i].alarmState = SI_STATE_IDLE;
	//					SI_NS_alarmIDLE(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
					}
				}
				break;
		}
	}
//	if ((SI_threadInfo[i].adcState == SI_ADC_FAULT) && (SI_threadInfo[i].faultState > SI_STATE_IDLE))
	if ((SI_threadInfo[i].adcState == SI_ADC_FAULT) && (alarmState > SI_STATE_IDLE) && (alarmState != SI_STATE_NS_resetOff) && (alarmState != SI_STATE_NS_resetOn))
	{
//		SI_threadInfo[i].alarmState = SI_STATE_IDLE;
//		SI_NS_alarmIDLE(SI_threadInfo[i].alarmLed, SI_threadInfo[i].globalAlarmLed);
		SOSZ_clearSOSZ_SILoAlm(1<<i);
	}
}
